﻿using System;
using System.Linq;
using System.Data;
using System.Reflection;
using System.Data.Entity;
using GBlog.Core.Mapping;
using GBlog.Core.Entities;
using System.Collections.Generic;
using System.Data.Entity.Validation;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace GBlog.Core.Data.Default
{
    public class GContext : DbContext, IDbContext
    {
        public override int SaveChanges()
        {
            var Entities = ChangeTracker.Entries<EntityBase>().Where(e => e.State == EntityState.Modified);
            foreach (var Entity in Entities)
            {
                if (Entity.Entity.Created == default(DateTime))
                {
                    Entity.Entity.Created = DateTime.Now;
                }
            }

            try
            {
                return base.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {
                var errors = ex.EntityValidationErrors.Where(e => !e.IsValid).Select(e => e.Entry.Entity.GetType().Name + " - Errors: " + string.Join(", ", e.ValidationErrors.Select(v => v.PropertyName + ": " + v.ErrorMessage)));
                throw;
            }
            catch { throw; }
        }

        public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
        {
            return base.Set<TEntity>();
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            List<Type> typesToRegister = new List<Type>();
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                var types = assembly.GetTypes().Where(type => !String.IsNullOrEmpty(type.Namespace)).Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(MapBase<,>));
                typesToRegister.AddRange(types);
            }
            foreach (var type in typesToRegister)
            {
                dynamic configurationInstance = Activator.CreateInstance(type);
                modelBuilder.Configurations.Add(configurationInstance);
            }
            modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
            base.OnModelCreating(modelBuilder);
        }
    }
}